import random
import numpy as np
class Agentlayer(object):
    """AI player based on MCTS"""

    def __init__(self,dqn):
        self.dqn=dqn

    def set_player_ind(self, p):
        self.player = p

    def reset_player(self):
        pass

    def get_action(self, board):
        sensible_moves = board.availables
        if len(sensible_moves)>61:
            for item in sensible_moves:
                h,w = board.move_to_location(item)
                if h<=5 and h>=3 and w>=3 and w<=5:
                    return item
        state=board.current_state()
        Q_value = self.dqn.Q_value.eval(feed_dict={
            self.dqn.input_states: [state]
        })[0]
        #print('Q_value:',Q_value)
        Q_value_index_list = np.argsort(Q_value)
        print('Q_value_index_list:', Q_value_index_list)
        for i in range(1, len(Q_value_index_list)+1):
            if Q_value_index_list[len(Q_value_index_list) - i] in sensible_moves:
                return Q_value_index_list[len(Q_value_index_list) - i]


    def __str__(self):
        return "Agentlayer {}".format(self.player)






from game_env import Board, Game
from DQN import DQN

# from policy_value_net import PolicyValueNet  # Theano and Lasagne
# from policy_value_net_pytorch import PolicyValueNet  # Pytorch
# from policy_value_net_tensorflow import PolicyValueNet # Tensorflow
# from policy_value_net_keras import PolicyValueNet  # Keras


class Human(object):
    """
    human player
    """

    def __init__(self):
        self.player = None

    def set_player_ind(self, p):
        self.player = p

    def get_action(self, board):
        try:
            location = input("Your move: ")
            if isinstance(location, str):  # for python3
                location = [int(n, 10) for n in location.split(",")]
            move = board.location_to_move(location)
        except Exception as e:
            move = -1
        if move == -1 or move not in board.availables:
            print("invalid move")
            move = self.get_action(board)
        return move

    def __str__(self):
        return "Human {}".format(self.player)


def run():
    n = 5
    width, height = 8, 8
    model_file = 'best_policy_8_8_5.model'
    try:
        board = Board(width=width, height=height, n_in_row=n)
        game = Game(board)

        # ############### human VS AI ###################
        # load the trained policy_value_net in either Theano/Lasagne, PyTorch or TensorFlow

        # best_policy = PolicyValueNet(width, height, model_file = model_file)
        # mcts_player = MCTSPlayer(best_policy.policy_value_fn, c_puct=5, n_playout=400)

        # load the provided model (trained in Theano/Lasagne) into a MCTS player written in pure numpy
        agent = DQN(model_file='./current_policy.model')

        # human player, input your move in the format: 2,3
        human = Human()
        mAgentlayer=Agentlayer(agent)
        # set start_player=0 for human first
        game.start_play(human, mAgentlayer, start_player=1, is_shown=1)
    except KeyboardInterrupt:
        print('\n\rquit')


if __name__ == '__main__':
    run()
